/*
 * Copyright (c) 2023 Huawei Technologies Co., Ltd.
 * openUBMC is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *         http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

#ifndef HI182X_PORT_H
#define HI182X_PORT_H

#include <imu/imu.h>
#include <mc/engine.h>
#include <ncsi_over_mctp/ncsi_over_mctp_huawei.h>
#include <smbus/smbus.h>
#include <unordered_map>
#include <mc/variant.h>

#include "hi182x_om.h"
#include "interface/network_port.h"
#include "interface/network_port/data_center_bridging.h"
#include "interface/network_port/link_info.h"
#include "interface/network_port/lldp_receive.h"
#include "interface/network_port/metrics.h"

namespace dev {
using ncsi_over_mctp_hw_ptr = std::shared_ptr<ncsi_over_mctp_huawei>;

// LLDP接收属性映射表
static const std::unordered_map<std::string, std::string> lldp_receive_mds_name_map = {
    {"ChassisId", "chassis_id"},
    {"ChassisIdSubtype", "chassis_id_subtype"},
    {"PortId", "port_id"},
    {"PortIdSubtype", "port_id_subtype"},
    {"SystemName", "system_name"},
    {"ManagementVlanId", "vlan_id"}
};

// 默认LLDP接收数据
static const std::unordered_map<std::string, mc::variant> default_lldp_receive_data = {
    {"ChassisId", std::string("")},
    {"ChassisIdSubtype", std::string("")},
    {"PortId", std::string("")},
    {"PortIdSubtype", std::string("")},
    {"SystemName", std::string("")},
    {"ManagementVlanId", static_cast<uint16_t>(0xFFFF)}
};

class hi182x_port : public mc::engine::object<hi182x_port> {
public:
    MC_OBJECT(
        hi182x_port, "NicPort", "NicPort/${PortId}",
        (NetworkPort)(NetworkPort_LinkInfo)(NetworkPort_DataCenterBridging)(NetworkPort_LLDPReceive)(NetworkPort_Metrics))
    hi182x_port()  = default;
    ~hi182x_port() = default;
    bool start();
    bool stop();
    bool init(mc::mutable_dict& csr_object, const mc::dict& connector);

    bool start_ncsi_protocol(ncsi_over_mctp_hw_ptr ncsi_over_mctp, mc::milliseconds interval);
    void stop_ncsi_protocol();
    bool start_smbus_update_task(smbus_obj_ptr smbus_obj, mc::milliseconds interval);
    bool init_optical_module();
    bool update_port_bdf(imu_pcie_device_req_t& pcie_device_info);
    bool verify_did_vid_svid_sdid(imu_pcie_device_req_t& pcie_device_info);
    
    // LLDP相关方法
    void update_lldp_receive(const mc::dict& lldp_rsp, const mc::mutable_dict& parsed_data);
    void update_network_port_lldp_receive(const mc::mutable_dict& data);
    bool enable_lldp_over_mctp();

private:
    // LLDP启用重试相关的内部方法
    void try_enable_lldp_internal();
    void schedule_lldp_retry();
    void cleanup_lldp_retry_timer();

public:
    NetworkPort                    m_network_port;
    NetworkPort_LinkInfo           m_network_port_link_info;
    NetworkPort_DataCenterBridging m_network_port_data_center_bridging;
    NetworkPort_LLDPReceive        m_network_port_lldp_receive;
    NetworkPort_Metrics            m_network_port_metrics;

    hi182x_optical_module* m_optical_module;
    
    // IMU对象，用于PCI信息验证
    std::unique_ptr<imu> m_imu;
    
    mc::core::timer* m_lldp_clear_timer = nullptr;
};

} // namespace dev

#endif // HI182X_PORT_H
